package com.sright.bcard.common.biz.manager.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.mts.model.v20140618.QueryJobListRequest;
import com.aliyuncs.mts.model.v20140618.QueryJobListResponse;
import com.aliyuncs.mts.model.v20140618.SubmitJobsRequest;
import com.aliyuncs.mts.model.v20140618.SubmitJobsResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.sright.bcard.common.biz.manager.VideoConvertManager;
import com.sright.bcard.common.service.share.dto.properties.TranscodeProperties;
import com.sright.bcard.common.service.share.exception.base.BusinessErrorException;
import com.sright.bcard.common.service.share.exception.code.BusinessCode;
import com.sright.bcard.content.dal.dao.MaterialDAO;
import com.sright.bcard.content.dal.dao.TranscodeDAO;
import com.sright.bcard.content.dal.entity.MaterialDO;
import com.sright.bcard.content.dal.entity.TranscodeDO;
import com.sright.common.response.SrightResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import shaded.com.google.gson.Gson;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
public class VideoConvertManagerImpl implements VideoConvertManager {

    @Value("${aliyun.miniapp.transcode.access-key-id}")
    private String AccessKeyId;

    @Value("${aliyun.miniapp.transcode.access-key-secret}")
    private String AccessKeySecret;

    @Value("${aliyun.miniapp.transcode.mps-region-id}")
    private String MpsRegionId;

    @Value("${aliyun.miniapp.transcode.transcode-pipe-line-id}")
    private String TranscodePipeLineId;

    @Value("${aliyun.miniapp.transcode.media-pipe-line-id}")
    private String MediaPipeLineId;

    @Value("${aliyun.miniapp.transcode.oss-bucket}")
    private String Bucket;

    @Value("${aliyun.miniapp.transcode.oss-location}")
    private String Location;

    @Value("${aliyun.miniapp.transcode.oss-endpoint}")
    private String Endpoint;

    @Value("${aliyun.miniapp.transcode.media-type2-template-id-map.card_media}")
    private String MediaType2TemplateMap_CardMedia;

    @Autowired
    private TranscodeDAO transcodeDAO;

    @Autowired
    private MaterialDAO materialDAO;

    public SubmitJobsResponse transcode(String sourceKey, String targetKey, String templateId,Long materialId) {
        TranscodeProperties transcodeProperties = new TranscodeProperties();
        transcodeProperties.setAccessKeyId(AccessKeyId);
        transcodeProperties.setAccessKeySecret(AccessKeySecret);
        transcodeProperties.setMpsRegionId(MpsRegionId);
        transcodeProperties.setTranscodePipeLineId(TranscodePipeLineId);
        transcodeProperties.setMediaPipeLineId(MediaPipeLineId);
        transcodeProperties.setOssEndpoint(Endpoint);
        transcodeProperties.setOssLocation(Location);
        transcodeProperties.setOssBucket(Bucket);
        Map<String ,String> mediaType2TemplateMap = new HashMap<String ,String>();
        mediaType2TemplateMap.put("card_media",MediaType2TemplateMap_CardMedia);
        transcodeProperties.setMediaType2TemplateIdMap(mediaType2TemplateMap);

        return transcode(transcodeProperties, sourceKey, targetKey, templateId);
    }

    /**
     * 创建DefaultAcsClient实例并初始化
     *
     * @return IAcsClient
     */
    private static IAcsClient getIAcsClient(TranscodeProperties transcodeProperties) {
        DefaultProfile profile = DefaultProfile.getProfile(
                transcodeProperties.getMpsRegionId(),           // 地域ID
                transcodeProperties.getAccessKeyId(),       // 您的AccessKey ID
                transcodeProperties.getAccessKeySecret()    // 您的AccessKey Secret
        );
        return new DefaultAcsClient(profile);
    }

    /**
     * 根据任务ID获取转码结果
     * @param jobId 任务ID
     * @return
     */
    public QueryJobListResponse getJobByJobId(String jobId) {
        TranscodeProperties transcodeProperties = new TranscodeProperties();
        transcodeProperties.setAccessKeyId(AccessKeyId);
        transcodeProperties.setAccessKeySecret(AccessKeySecret);
        transcodeProperties.setMpsRegionId(MpsRegionId);

        // 创建API请求并设置参数
        QueryJobListRequest request = new QueryJobListRequest();

        // 转码作业ID列表，逗号分隔，一次最多10个
        request.setJobIds(jobId);
        // 发起请求并处理应答或异常
        try {
            QueryJobListResponse response = getIAcsClient(transcodeProperties).getAcsResponse(request);
            System.out.println(new Gson().toJson(response));
            return response;
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return null;
    }

    protected SubmitJobsResponse innerTranscode(TranscodeProperties transcodeProperties, String ossLocation, String ossBucket, String inputOssKey, String outputOssKey, String templateId, String pipelineId) {
        DefaultProfile profile = DefaultProfile.getProfile(transcodeProperties.getMpsRegionId(), transcodeProperties.getAccessKeyId(), transcodeProperties.getAccessKeySecret());
        IAcsClient client = new DefaultAcsClient(profile);
        // 创建API请求并设置参数
        SubmitJobsRequest request = new SubmitJobsRequest();
        // Input
        JSONObject input = new JSONObject();
        input.put("Location", ossLocation);
        input.put("Bucket", ossBucket);
        String outputOSSObject;
        try {
            input.put("Object", URLEncoder.encode(inputOssKey, "utf-8"));
            request.setInput(input.toJSONString());
            outputOSSObject = URLEncoder.encode(outputOssKey, "utf-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("output URL encode failed");
        }
        JSONObject output = new JSONObject();
        output.put("OutputObject", outputOSSObject);
        output.put("TemplateId", templateId);
        JSONArray outputs = new JSONArray();
        outputs.add(output);
        request.setRegionId(transcodeProperties.getMpsRegionId());
        request.setOutputs(outputs.toJSONString());
        request.setOutputBucket(ossBucket);
        request.setOutputLocation(ossLocation);
        // PipelineId
        request.setPipelineId(pipelineId);
        // 发起请求并处理应答或异常
        SubmitJobsResponse response = null;
        try {
            response = client.getAcsResponse(request);
            System.out.println("RequestId is:" + response.getRequestId());
            if (response.getJobResultList().get(0).getSuccess()) {
                System.out.println("JobId is:" + response.getJobResultList().get(0).getJob().getJobId());
            } else {
                System.out.println("SubmitJobs Failed code:" + response.getJobResultList().get(0).getCode() + " message:" + response.getJobResultList().get(0).getMessage());
            }
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return response;
    }

    public SubmitJobsResponse transcode(TranscodeProperties transcodeProperties, String sourceKey, String targetKey, String templateId) {
        if (!StringUtils.isNotBlank(templateId)) {
            throw new BusinessErrorException(BusinessCode.TRANSCODE_TEMPLATE_NOT_EXIST);
        }
        String pipeLineId = transcodeProperties.getTranscodePipeLineId();
        String ossLocation = transcodeProperties.getOssLocation();
        String bucket = transcodeProperties.getOssBucket();
        return innerTranscode(transcodeProperties, ossLocation, bucket, sourceKey, targetKey, templateId, pipeLineId);
    }

    @Override
    public SrightResponse callback(String mtsRequest) {
        log.info("转码回调参数 : {}", mtsRequest);
        //{"TopicOwner":"1108658122386375","Message":"{\"jobId\":\"dda0cb33df7942a291ada7211ae47794\",\"requestId\":\"AED670D2-6FE3-443D-B5A1-127A3C9144B0\",\"Type\":\"Transcode\",\"state\":\"Success\",\"type\":\"Transcode\",\"State\":\"Success\",\"JobId\":\"dda0cb33df7942a291ada7211ae47794\",\"RequestId\":\"AED670D2-6FE3-443D-B5A1-127A3C9144B0\"}","Subscriber":"1108658122386375","PublishTime":"1602309164002","SubscriptionName":"cuface??","MessageMD5":"974D22D1D6AD9AC8D6518EC95B8635A0","TopicName":"eg-transcode-service","MessageId":"615F58DFDEA0630D7FD131539FE2511E"}
        JSONObject request = JSONObject.parseObject(mtsRequest);
        String message = request.getString("Message");
        JSONObject messageJson = JSONObject.parseObject(message);
        String jobId = messageJson.getString("jobId");
        TranscodeDO transcodeDO = transcodeDAO.selectByJobId(jobId);
        if (transcodeDO == null) {
            return SrightResponse.defaultSuccess();
        } else {
            QueryJobListResponse queryJobListResponse = getJobByJobId(jobId);
            QueryJobListResponse.Job job = queryJobListResponse.getJobList().get(0);
            transcodeDO.setStatus(job.getState());
            transcodeDO.setOutput(job.getOutput().getOutputFile().getObject());
            transcodeDAO.updateSelective(transcodeDO);

            //更新素材表字段
            MaterialDO materialDO = materialDAO.selectById(transcodeDO.getMaterialId());
            if (materialDO == null) {
                return SrightResponse.defaultSuccess();
            } else {
                materialDAO.updateSelective(materialDO);
            }
            return SrightResponse.defaultSuccess();
        }
    }

    @Override
    public Boolean materialTranscode(Long materialId, String sourceKey, Integer materialType) {
        //根据素材类型选择转码素材
        String[] strArray = sourceKey.split("\\.");
        if (materialType == 4 || materialType == 8) {
            //横视频转码模板
            String targetKey540P = strArray[0] + "_540p.mp4";
            SubmitJobsResponse result1 = transcode(sourceKey,targetKey540P,"572224cb71e84684fd0f787aeb910921",materialId);  //540P
            saveTranscodeData(result1,materialId,"572224cb71e84684fd0f787aeb910921");

            String targetKey720P = strArray[0] + "_720p.mp4";
            SubmitJobsResponse result2 = transcode(sourceKey,targetKey720P,"d73d0055f28b45f79bf95397b24c970a",materialId);  //720P
            saveTranscodeData(result2,materialId,"d73d0055f28b45f79bf95397b24c970a");

            String targetKey1080P = strArray[0] + "_1080p.mp4";
            SubmitJobsResponse result3 = transcode(sourceKey,targetKey1080P,"7f93770ea67c4b35928de6b0317f926f",materialId);  //1080P
            saveTranscodeData(result3,materialId,"7f93770ea67c4b35928de6b0317f926f");
        } else if (materialType == 1 || materialType == 6) {
            //竖视频转码模板
            String targetKey540P = strArray[0] + "_540p.mp4";
            SubmitJobsResponse result1 = transcode(sourceKey,targetKey540P,"1d8a449badd94f25ac8e9d1456918d10",materialId);  //540P
            saveTranscodeData(result1,materialId,"1d8a449badd94f25ac8e9d1456918d10");

            String targetKey720P = strArray[0] + "_720p.mp4";
            SubmitJobsResponse result2 = transcode(sourceKey,targetKey720P,"9728e60a10f448179761ebf32b6cd22e",materialId);  //720P
            saveTranscodeData(result2,materialId,"9728e60a10f448179761ebf32b6cd22e");

            String targetKey1080P = strArray[0] + "_1080p.mp4";
            SubmitJobsResponse result3 = transcode(sourceKey,targetKey1080P,"a61c33cee10247908ac0fe1144b4358c",materialId);  //1080P
            saveTranscodeData(result3,materialId,"a61c33cee10247908ac0fe1144b4358c");
        } else {
            return true;
        }
        return true;
    }

    public void saveTranscodeData(SubmitJobsResponse response,Long materialId,String templateId) {
        TranscodeDO transcodeDO = new TranscodeDO();
        transcodeDO.setJobId(response.getJobResultList().get(0).getJob().getJobId());
        transcodeDO.setMaterialId(materialId);
        transcodeDO.setTemplateId(templateId);
        transcodeDO.setStatus(response.getJobResultList().get(0).getJob().getState());
        transcodeDAO.insertSelective(transcodeDO);
    }
}
